package com.education.common.model;

import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.hutool.core.bean.BeanUtil;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录后Token的生成和解析
 * @author 余一
 * @date 2021/9/14  15:42
 */
public class JwtToken {
    private static final Logger logger = LoggerFactory.getLogger(JwtToken.class);
    private final String secret;

    public JwtToken(String secret) {
        if (secret == null) {
            throw new NullPointerException("secret can not be null.");
        }
        this.secret = secret;
    }

    /**
     * 创建JwtToken
     * @param value
     * @param expirationTime
     * @return
     */
    public String createJwtToken(Object value,long expirationTime){
        SecretKey secretKey = generalKey(secret);
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        String subject = JSONObject.toJSONString(value);
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder jwtBuilder = Jwts.builder()
                .setIssuedAt(now)
                .setSubject(subject)
                .signWith(signatureAlgorithm, secretKey);
        if (expirationTime > 0L) {
            long expMillis = nowMillis + expirationTime;
            Date exp = new Date(expMillis);
            jwtBuilder.setExpiration(exp);
        }
        return jwtBuilder.compact();
    }

    /**
     * 解析token
     * @param token
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T parseToken(String token,Class<T> clazz){
        SecretKey secretKey = this.generalKey(secret);
        try {
            Claims claims = (Claims) Jwts.parser().setSigningKey(secretKey);
            String subject = claims.getSubject();
            if (BeanUtil.isEmpty(subject)) {
                return null;
            }
            return JSONObject.parseObject(subject,clazz);
        }catch (SignatureException | MalformedJwtException e){
            logger.error("Jwt 签名错误或解析错误");
        }catch (Exception e){
            logger.error(e.getMessage());
        }
        return null;
    }

    public Map<Object,String> parseToken(String token){
        return parseToken(token, HashMap.class);
    }

    /**
     * 获取解析后的字符串
     * @param token
     * @return
     */
    public String parseTokenToString(String token){
        return parseToken(token, String.class);
    }

    private SecretKey generalKey(String secret){
        byte[] encodeKey = DatatypeConverter.parseBase64Binary(secret);
        SecretKeySpec key = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");
        return key;
    }
}
